<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';

import { AuthenticationQrCodeLogin } from '@vben/common-ui';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';

import { QRCode } from 'ant-design-vue';

import { loadQrcodeSessionApi } from '#/api/app';
import { useAuthStore } from '#/store';

defineOptions({ name: 'QrCodeLogin' });

const text = ref('no-session');
const authStore = useAuthStore();

const status = ref();
const description = ref('');
const sseClientId = ref();
const sse = ref();

function connectServer(sessionId: string) {
  const eventSource = new EventSource(
    `${import.meta.env.VITE_SOCK_URL}/sse/connect/public?clientId=${sessionId}`,
  );
  sse.value = eventSource;
  eventSource.addEventListener('message', (event) => {
    handleMessage(event.data);
  });
  eventSource.addEventListener('error', () => {
    eventSource.close();
  });
}

function disconnectServer() {
  if (sse.value) {
    sse.value.close();
  }
}

function handleMessage(message: string) {
  const returnData = JSON.parse(message);
  if (returnData.title === 'scanned') {
    handleScanned();
  }
  if (returnData.title === 'login') {
    handleLogin(sseClientId.value, returnData.content);
  }
  if (returnData.title === 'expired') {
    handleExpired();
  }
}

function handleScanned() {
  status.value = 'scanned';
  description.value = $t('page.auth.qrcodeScannedDesc');
}

function handleLogin(username: string, verifyCode: string) {
  const authenticationFactors = [
    { type: 'QRCODE', username, credential: { username, verifyCode } },
  ];
  authStore.authLogin(authenticationFactors);
}

function handleExpired() {
  description.value = $t('page.auth.qrcodeExpiredDesc');
  status.value = 'expired';
  disconnectServer();
}

async function createQrcode() {
  status.value = 'loading';

  const { sessionId } = await loadQrcodeSessionApi();
  sseClientId.value = sessionId;
  const expireIn = 300_000;
  text.value = sessionId;
  description.value = '';
  disconnectServer();
  connectServer(sessionId);

  const timer = setInterval(() => {
    clearInterval(timer);
    handleExpired();
  }, expireIn);

  status.value = 'active';
}

async function refreshQrcode() {
  createQrcode();
}

onMounted(() => {
  createQrcode();
});

onUnmounted(() => {
  disconnectServer();
});
</script>

<template>
  <AuthenticationQrCodeLogin
    :description="description"
    :login-path="LOGIN_PATH"
  >
    <template #qrcode>
      <QRCode :status="status" :value="text" @refresh="refreshQrcode" />
    </template>
  </AuthenticationQrCodeLogin>
</template>
